package com.atguigu.tingshu.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.config.RabbitInitConfigApplicationListener;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.common.util.MD5;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.message.LocalMsg;
import com.atguigu.tingshu.model.order.OrderDerate;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.VipServiceConfig;
import com.atguigu.tingshu.order.adapter.PayWay;
import com.atguigu.tingshu.order.helper.SignHelper;
import com.atguigu.tingshu.order.mapper.LocalMsgMapper;
import com.atguigu.tingshu.order.mapper.OrderDerateMapper;
import com.atguigu.tingshu.order.mapper.OrderDetailMapper;
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.order.OrderDerateVo;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import com.atguigu.tingshu.vo.order.TradeVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;

    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;

    @Autowired
    private List<PayWay> payWayList;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private OrderDerateMapper orderDerateMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private LocalMsgMapper localMsgMapper;

    @Autowired
    private RabbitService rabbitService;
    @Autowired
    private RabbitInitConfigApplicationListener rabbitInitConfigApplicationListener;


    /**
     * 用户购买音频或专辑的订单结算页面展示
     * @param tradeVo 购买结算信息
     * @return 结算数据
     */
    @Override
    public OrderInfoVo trade(TradeVo tradeVo) {

        OrderInfoVo orderInfoVo = new OrderInfoVo();

        //1.获取当前用户的id
        Long userId = AuthContextHolder.getUserId();

        //2.获取当前结算信息中的itemType
        //  1001 - 购买整专辑 | 1002 - 购买音频 | 1003 - 购买vip会员
        String itemType = tradeVo.getItemType();

        //3.组装对象
        switch (itemType){
            //3.1 处理购买整专辑
            case "1001" :
                orderInfoVo = dealPurchaseWholeAlbum(tradeVo,userId);
                break;
            //3.2 处理购买指定数量的音频
            case "1002" :
                orderInfoVo = dealPurchaseTrack(tradeVo,userId);
                break;
            //3.3 处理购买VIP身份
            case "1003" :
                orderInfoVo = dealPurchaseVIP(tradeVo,userId);
        }

        //4.生成签名并赋值
        String jsonString = JSONObject.toJSONString(orderInfoVo);
        Map map = JSONObject.parseObject(jsonString, Map.class);
        String sign = SignHelper.getSign(map);
        orderInfoVo.setSign(sign);

        //5.将返回的商品集合id列表存入到redis中
        List<Long> itemIdList = orderInfoVo.getOrderDetailVoList().stream().map(OrderDetailVo::getItemId).toList();
        String encrypt = MD5.encrypt(itemIdList.toString());
        String multiportRepeatLockKey = userId + ":" + encrypt;
        redisTemplate.opsForValue().set(multiportRepeatLockKey,"1");

        //6.返回数据
        return orderInfoVo;
    }


    /**
     * 【整专辑购买】
     * 处理购买整专辑的情况，返回结算页面
     * @param tradeVo 结算信息
     * @param userId 用户id
     * @return 结算数据
     */
    private OrderInfoVo dealPurchaseWholeAlbum(TradeVo tradeVo, Long userId) {
        //1.创建我们需要返回的对象
        OrderInfoVo result = new OrderInfoVo();
        Long albumId = tradeVo.getItemId();
        String itemType = tradeVo.getItemType();

        //2.幂等性校验，我们先去校验当前用户是否买过当前专辑，防止重复购买
        Result<List<UserPaidAlbum>> userPaidAlbumResult = userInfoFeignClient.getUserPaidAlbumList(userId, albumId);
        List<UserPaidAlbum> userPaidAlbumData = userPaidAlbumResult.getData();
        Assert.notNull(userPaidAlbumData,"[OrderInfoServiceImpl] 调用user微服务的 [getUserPaidAlbumList]方法失败");
        if (!CollectionUtils.isEmpty(userPaidAlbumData)){
            log.error("该付款项目:{}已经购买过，请勿重复购买", albumId);
            throw new GuiguException(201,"当前用户已购买过这个专辑，请勿重复购买");
        }

        //3.判断当前专辑是否已经被用户购买了,即已创建订单，但是状态是[未支付]
        Boolean isPaying = orderInfoMapper.checkAlbumOrVipIsPaying(userId, albumId,itemType);
        if (isPaying){
            log.error("该付款项专辑：{}，处于购买中，请勿继续购买该专辑", albumId);
            throw new GuiguException(201,"当前专辑正在支付中,请勿重复购买");
        } else {

            //4.若没有处在支付状态，那么就允许走接下来流程
            //4.1 设置订单号
            String tradeNo = RandomStringUtils.random(12, true, true);
            result.setTradeNo(tradeNo);

            //4.2 设置支付方式
            result.setPayWay("");

            //4.3 设置订单类型
            result.setItemType(itemType);

            //4.4 根据专辑id获取专辑对象
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
            AlbumInfo albumInfo = albumInfoResult.getData();
            Assert.notNull(albumInfo,"[OrderInfoServiceImpl]调用album微服务的[getAlbumInfo]方法出错");

            //4.4.1 根据专辑对象，获取价格信息
            BigDecimal price = albumInfo.getPrice();

            //4.4.2 根据当前用户id，判断当前用户是否是VIP用户，若是，则使用vip则可，反之使用普通折扣信息
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo,"[OrderInfoServiceImpl]调用user微服务的[getUserInfoVo]方法出错");
            Integer isVip = userInfoVo.getIsVip();

            //4.4.3 根据当前用户身份，获取折扣信息
            BigDecimal discount = null;
            if ("1".equals(isVip)){
                discount = albumInfo.getVipDiscount();
            } else {
                discount = albumInfo.getDiscount();
            }
            if (discount.intValue() == -1){
                discount = new BigDecimal("10.00");
            }

            //4.4.4
            //根据目前的折扣值来获取优惠金额以及优惠过后的订单总价
            //优惠金额 = 总价 - (总价 * (折扣/10) )
            //优惠后的最终价格 = 总价 - 优惠金额
//            BigDecimal derateAmount = price.subtract(price.multiply(discount.divide(new BigDecimal("10"))));
            BigDecimal derateAmount = price.subtract(price.multiply(discount.divide(new BigDecimal("10.00"))));
            BigDecimal orderAmount =  price.subtract(derateAmount);

            //4.4.5 给原价以及优惠信息赋值
            result.setDerateAmount(derateAmount.setScale(2, RoundingMode.HALF_UP));
            result.setOrderAmount(orderAmount.setScale(2, RoundingMode.HALF_UP));
            result.setOriginalAmount(price);

            //4.4.6 orderDetailVoList属性赋值
            List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
            OrderDetailVo orderDetailVo = new OrderDetailVo();
            orderDetailVo.setItemId(albumId);
            orderDetailVo.setItemName(albumInfo.getAlbumTitle());
            orderDetailVo.setItemUrl(albumInfo.getCoverUrl());
            orderDetailVo.setItemPrice(albumInfo.getPrice());
            orderDetailVoList.add(orderDetailVo);
            result.setOrderDetailVoList(orderDetailVoList);
            
            //4.4.7 orderDerateVoList属性赋值
            List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
            OrderDerateVo orderDerateVo = new OrderDerateVo();
            orderDerateVo.setDerateType("专辑折扣");
            orderDerateVo.setDerateAmount(derateAmount);
            orderDerateVo.setRemarks("订单减免类型专辑折扣见面");
            orderDerateVoList.add(orderDerateVo);
            result.setOrderDerateVoList(orderDerateVoList);

            //4.4.8 Timestamp属性赋值
            result.setTimestamp(System.currentTimeMillis());

            //4.5 返回
            return result;
        }
    }


    /**
     * 【单集购买】
     * 处理购买指定数量的音频
     * @param tradeVo 结算信息
     * @param userId 用户id
     * @return 结算数据
     */
    private OrderInfoVo dealPurchaseTrack(TradeVo tradeVo, Long userId) {
        //1.定义需要返回的对象
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        //获取购买集数
        Integer trackCount = tradeVo.getTrackCount();
        //获取用户点击的音频对象的音频id
        Long trackId = tradeVo.getItemId();
        //获取itemType
        String itemType = tradeVo.getItemType();

        //2.根据音频id获取音频对象，根据音频对象获取专辑id，根据专辑id获取专辑对象
        Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfoById(trackId);
        TrackInfo trackInfo = trackInfoResult.getData();
        Assert.notNull(trackInfo,"[OrderInfoServiceImpl]调用album微服务的[getTrackInfoById]方法出错");
        //获取专辑id
        Long albumId = trackInfo.getAlbumId();
        //获取专辑对象
        Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
        AlbumInfo albumInfo = albumInfoResult.getData();
        Assert.notNull(albumInfo,"[OrderInfoServiceImpl]调用album微服务的[getAlbumInfo]方法出错");

        //3.幂等性校验，我们根据用户返回过来的trackCount，即购买集数等信息去后台查询需要具体返回给用户的可购买音频列表
        Result<List> canPaidTrackInfoListResult = albumInfoFeignClient.getCanPaidTrackInfoList(userId,albumId,trackId,trackCount);
        Integer code = canPaidTrackInfoListResult.getCode();
        if (code == 400){
            orderInfoVo.setExitItemIds(canPaidTrackInfoListResult.getData());
            return orderInfoVo;
        }
        //经过一次过滤后可以购买的音频数据列表
        List<Map> canPaidTrackInfoList = canPaidTrackInfoListResult.getData();
        Assert.notNull(canPaidTrackInfoList,"[OrderInfoServiceImpl]调用album微服务的[getCanPaidTrackInfoList]方法出错");

        //4.去判断当前用户是否存在正在支付的
        List<Long> paddingTrackIds = orderInfoMapper.checkTrackTypeItemPadding(itemType, userId);

        List<Map> paddingTrackIdList = canPaidTrackInfoList.stream().filter(map -> paddingTrackIds.contains(map.get("id"))).collect(Collectors.toList());
        List<Object> exitTrackList = new ArrayList<>();
        // 要买的有声音中有存在支付中，收集起来返回给前端
        if (!CollectionUtils.isEmpty(paddingTrackIdList)) {
            for (Map map : paddingTrackIdList) {
                exitTrackList.add(map.get("id"));
                log.error("该付款项声音：{}，处于购买中，请勿继续购买该声音", map.get("id"));
            }
            // 收集起来返给前端
            orderInfoVo.setExitItemIds(exitTrackList);
            return orderInfoVo;
        } else {
            orderInfoVo.setTradeNo(RandomStringUtils.random(12, true, true));
            orderInfoVo.setPayWay("");
            orderInfoVo.setItemType(tradeVo.getItemType());
            BigDecimal trackPrice = albumInfo.getPrice();
            BigDecimal originAmount = trackCount == 0 ? trackPrice : trackPrice.multiply(new BigDecimal(trackCount));
            orderInfoVo.setOriginalAmount(originAmount.setScale(2, RoundingMode.HALF_UP)); // 原始价格
            orderInfoVo.setDerateAmount(new BigDecimal("0.00")); // 优惠价格
            orderInfoVo.setOrderAmount(originAmount.setScale(2, RoundingMode.HALF_UP));// 实际金额
            ArrayList<OrderDetailVo> orderDetailVos = new ArrayList<>();
            for (Map map : canPaidTrackInfoList) {
                OrderDetailVo orderDetailVo = new OrderDetailVo();
                Object id = map.get("id");
                orderDetailVo.setItemId(Long.parseLong(id + ""));
                orderDetailVo.setItemName((String) map.get("trackTitle"));
                orderDetailVo.setItemUrl((String) map.get("coverUrl"));
                orderDetailVo.setItemPrice(trackPrice.setScale(2, RoundingMode.HALF_UP));
                orderDetailVos.add(orderDetailVo);
            }
            orderInfoVo.setOrderDetailVoList(Lists.newArrayList(orderDetailVos));
            orderInfoVo.setOrderDerateVoList(Lists.newArrayList());// 声音不打折
            orderInfoVo.setTimestamp(System.currentTimeMillis());
            return orderInfoVo;
        }
    }


    /**
     * 【购买VIP】
     * 处理用户购买VIP
     * @param tradeVo 结算信息
     * @param userId 用户id
     * @return 结算数据
     */
    private OrderInfoVo dealPurchaseVIP(TradeVo tradeVo, Long userId) {
        //1.创建我们需要返回的对象
        OrderInfoVo result = new OrderInfoVo();
        //获取vip套餐的id
        Long itemId = tradeVo.getItemId();
        //获取itemType
        String itemType = tradeVo.getItemType();

        //2.因为是购买vip，允许重复购买，不需要进行幂等性校验
        //直接去判断当前用户订单记录中是否存在正常支付未完成的订单
        Boolean isPaying = orderInfoMapper.checkAlbumOrVipIsPaying(userId, itemId,itemType);
        if (isPaying){
            log.error("该付款项vip套餐：{}，处于购买中，请勿继续购买该专辑", itemId);
            throw new GuiguException(201,"当前VIP购买请求正在支付中,请勿重复购买");
        } else {
            //3.对返回对象的基础属性进行赋值
            String tradeNo = RandomStringUtils.random(12, true, true);
            result.setTradeNo(tradeNo);
            result.setPayWay("");
            result.setItemType(itemType);

            //4.通过远程调用，获取vip套餐的具体信息
            Result<VipServiceConfig> vipConfigResult = userInfoFeignClient.getVipConfigById(itemId);
            VipServiceConfig vipConfig = vipConfigResult.getData();
            Assert.notNull(vipConfig,"[OrderInfoServiceImpl]调用user微服务的[getVipConfigById]方法出错");
            BigDecimal price = vipConfig.getPrice();
            BigDecimal discountPrice = vipConfig.getDiscountPrice();

            //5.获取到了价格以及折扣优惠数据，进行赋值
            BigDecimal derateAmount = price.subtract(discountPrice).setScale(2, RoundingMode.HALF_UP);
            result.setOriginalAmount(price.setScale(2, RoundingMode.HALF_UP));
            result.setDerateAmount(derateAmount); // 优惠了多少
            result.setOrderAmount(discountPrice.setScale(2, RoundingMode.HALF_UP)); // 实际金额

            //6.orderDetailVoList属性赋值
            List<OrderDetailVo> orderDetailVoList = new ArrayList<>();
            OrderDetailVo orderDetailVo = new OrderDetailVo();
            orderDetailVo.setItemId(itemId);
            orderDetailVo.setItemName(vipConfig.getName());
            orderDetailVo.setItemUrl(vipConfig.getImageUrl());
            orderDetailVo.setItemPrice(price.setScale(2, RoundingMode.HALF_UP));
            orderDetailVoList.add(orderDetailVo);
            result.setOrderDetailVoList(orderDetailVoList);

            //7.orderDerateVoList属性赋值
            List<OrderDerateVo> orderDerateVoList = new ArrayList<>();
            OrderDerateVo orderDerateVo = new OrderDerateVo();
            orderDerateVo.setDerateType("VIP服务折扣");
            orderDerateVo.setDerateAmount(derateAmount);
            orderDerateVo.setRemarks("订单减免类型1406-VIP服务折扣");
            orderDerateVoList.add(orderDerateVo);
            result.setOrderDerateVoList(orderDerateVoList);

            //8.Timestamp属性赋值
            result.setTimestamp(System.currentTimeMillis());

        }

        return result;
    }



    /**
     * 用户提交订单
     * @param orderInfoVo 订单数据
     * @return
     */
    @Override
    public Map<String, Object> submitOrder(OrderInfoVo orderInfoVo) {

        //1.获取用户id
        Long userId = AuthContextHolder.getUserId();

        //2.校验非法请求，即当前的订单参数中不存在订单号
        String tradeNo = orderInfoVo.getTradeNo();
        if (StringUtils.isEmpty(tradeNo)){
            throw new GuiguException(201,"请求非法");
        }

        //3.验签，防止订单信息被第三方篡改
        String jsonString = JSONObject.toJSONString(orderInfoVo);
        Map map = JSONObject.parseObject(jsonString, Map.class);
        map.put("payWay","");
        SignHelper.checkSign(map);

        //4.幂等性操作，防止订单重复提交
        /**
         * 这里我们采用redis来实现防止订单重复提交
         * 具体思路：
         * 0.我们在用户获取结算页面的时候，就将所有商品的id列表进行加密后，作为key，存入redis中
         * 1.我们将当前用户订单中购买音频的id列表进行加密，作为key
         * 2.去redis中查询该key是否存在数据
         * 3.如果存在，那么我们就删除这个key，并且进入订单业务处理流程
         */
        List<Long> itemIdList = orderInfoVo.getOrderDetailVoList().stream().map(OrderDetailVo::getItemId).toList();
        String encrypt = MD5.encrypt(itemIdList.toString());
        String multiportRepeatLockKey = userId + ":" + encrypt;
        String luaScript = "if redis.call(\"exists\",KEYS[1]) then return redis.call(\"del\",KEYS[1]) else return 0 end";
        Long execute = redisTemplate.execute(new DefaultRedisScript<Long>(luaScript, Long.class), List.of(multiportRepeatLockKey));
        if (execute == 0){
            throw new GuiguException(ResultCodeEnum.REPEAT_SUBMIT);
        }

        //5.根据传来的订单参数的支付类型，选择不同的支付业务进行订单业务处理
        String orderNo = RandomStringUtils.random(15,true,false);
        String payWay = orderInfoVo.getPayWay();
        for (PayWay way : payWayList) {
            if (way.isThisWay(payWay)){
                way.payWay(orderInfoVo, orderNo, userId);
            }
        }

        //6.将订单号组装map返回
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("orderNo",orderNo);
        return resultMap;
    }


    /**
     * 保存订单信息
     * @param orderInfoVo 订单信息
     * @param orderNo 订单号
     * @param userId 用户id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderInfo saveOrderInfo(OrderInfoVo orderInfoVo, String orderNo, Long userId) {
        OrderInfo orderInfo = null;

        try {
            //1.保存订单基本信息
            orderInfo = saveOrderBasicInfo(orderNo,orderInfoVo,userId);

            //2.保存订单减免信息
            saveOrderDerateInfo(orderInfoVo,orderInfo.getId());

            //3.保存订单详情信息
            saveOrderDetailInfo(orderInfoVo,orderInfo.getId());
        } catch (Exception e) {
            throw new GuiguException(201,"保存订单信息业务中间产生了异常");
        }

        return orderInfo;
    }


    /**
     * 保存订单详情信息
     * @param orderInfoVo 订单信息
     * @param id 订单id
     */
    private void saveOrderDetailInfo(OrderInfoVo orderInfoVo, Long id) {
        List<OrderDetailVo> orderDetailVoList = orderInfoVo.getOrderDetailVoList();
        orderDetailVoList.stream().forEach(vo ->{
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(id);
            orderDetail.setItemId(vo.getItemId());
            orderDetail.setItemName(vo.getItemName());
            orderDetail.setItemUrl(vo.getItemUrl());
            orderDetail.setItemPrice(vo.getItemPrice());

            int count = orderDetailMapper.insert(orderDetail);
            log.info("[saveOrderDetailInfo]订单详情信息保存结果:{}",count > 0 ? "success" : "fail");
        });
    }

    /**
     * 保存订单减免信息
     * @param orderInfoVo 订单信息
     * @param id 订单id
     */
    private void saveOrderDerateInfo(OrderInfoVo orderInfoVo, Long id) {
        List<OrderDerateVo> orderDerateVoList = orderInfoVo.getOrderDerateVoList();

        orderDerateVoList.stream().forEach(vo -> {
            OrderDerate orderDerate = new OrderDerate();
            orderDerate.setOrderId(id);
            orderDerate.setDerateType(vo.getDerateType());
            orderDerate.setDerateAmount(vo.getDerateAmount());
            orderDerate.setRemarks(vo.getRemarks());

            int count = orderDerateMapper.insert(orderDerate);
            log.info("[saveOrderDerateInfo]订单减免信息保存结果:{}",count > 0 ? "success" : "fail");
        });
    }

    /**
     * 保存订单基本信息
     * @param orderNo 订单号
     * @param orderInfoVo 订单信息
     * @return 订单对象
     */
    private OrderInfo saveOrderBasicInfo(String orderNo, OrderInfoVo orderInfoVo,Long userId) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setUserId(userId);
        orderInfo.setOrderTitle(orderInfoVo.getOrderDetailVoList().get(0).getItemName());
        orderInfo.setOrderNo(orderNo);
        orderInfo.setOrderStatus("0901");
        orderInfo.setOriginalAmount(orderInfoVo.getOriginalAmount());
        orderInfo.setDerateAmount(orderInfoVo.getDerateAmount());
        orderInfo.setOrderAmount(orderInfoVo.getOrderAmount());
        orderInfo.setItemType(orderInfoVo.getItemType());
        orderInfo.setPayWay(orderInfoVo.getPayWay());

        int count = orderInfoMapper.insert(orderInfo);
        log.info("[saveOrderBasicInfo]订单基本信息保存结果:{}",count > 0 ? "success" : "fail");

        return orderInfo;
    }

    /**
     * 保存本地消息表
     * @param orderNo 订单号
     */
    @Override
    public void saveLocalMsg(String orderNo) {
        LocalMsg msg = new LocalMsg();
        msg.setMsgContent(orderNo);
        msg.setStatus(0);
        msg.setCreateTime(new Date());
        msg.setUpdateTime(new Date());

        localMsgMapper.insert(msg);
    }


    /**
     * 根据订单号获取该订单详情
     * @param orderNo 订单号
     * @return 订单详情
     */
    @Override
    public OrderInfo getOrderInfoAndDetail(String orderNo) {
        //1.从数据库获取基本的订单信息
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getOrderNo,orderNo)
                .eq(OrderInfo::getIsDeleted,0);
        OrderInfo orderInfo = orderInfoMapper.selectOne(wrapper);

        //2.继续组装其他属性返回
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderInfo.getId()));
        orderInfo.setOrderDetailList(orderDetailList);
        List<OrderDerate> orderDerateList = orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderInfo.getId()));
        orderInfo.setOrderDerateList(orderDerateList);

        String orderStatus = orderInfo.getOrderStatus();
        String orderStatusName = getOrderStatusName(orderStatus);
        orderInfo.setOrderStatusName(orderStatusName);

        String payWay = orderInfo.getPayWay();
        String payWayName = getPayWayName(payWay);
        orderInfo.setPayWayName(payWayName);

        return orderInfo;
    }

    /**
     * 根据订单支付类型来获取具体的支付方式名称
     * @param payWay 支付方式
     * @return 支付方式名称
     */
    private String getPayWayName(String payWay) {
        String name = switch (payWay) {
            case "1101" -> "微信";
            case "1102" -> "支付宝";
            case "1103" -> "账户余额";
            default -> "";
        };
        return name;
    }


    /**
     * 根据订单的状态值-0901 -0902 -0903 获取具体的状态名称
     * @param orderStatus
     * @return
     */
    private String getOrderStatusName(String orderStatus) {
        String name = switch (orderStatus) {
            case "0901" -> "未支付";
            case "0902" -> "已支付";
            case "0903" -> "已取消";
            default -> "";
        };
        return name;
    }


    /**
     *  处理用户扣款成功后的一系列数据库操作
     * @param orderNo 订单号
     */
    @Override
    public void paySuccess(String orderNo) {
        //1.根据订单号获取订单的具体详情数据
        OrderInfo orderInfo = getOrderInfoAndDetail(orderNo);
        if (orderInfo == null){
            throw new GuiguException(201,"订单数据不存在!");
        }

        //2.修改订单的状态，即order_info表将status修改为支付成功 0901 -> 0902
        int count = orderInfoMapper.updateOrderStatusSuccess(orderNo);
        if (count == 0) {
            log.error("订单状态未修改成功");
        } else {
            log.info("订单状态修改成功");
        }

        //3.修改用户订单流水明细表
        UserPaidRecordVo userPaidRecordVo = prepareUserPaidRecordVo(orderInfo);
        rabbitService.sendMessage(MqConst.EXCHANGE_USER,MqConst.ROUTING_USER_PAY_RECORD,JSONObject.toJSONString(userPaidRecordVo));
        log.info("发送rabbitmq消息 -->  修改用户订单流水明细表");

        //4.修改ElasticSearch中的专辑购买量
        rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM_ES_STATA_UPDATE,MqConst.ROUTING_ALBUM_ES_STAT_UPDATE,orderNo);
        log.info("发送rabbitmq消息 -->  修改ElasticSearch中的专辑购买量维度数据");

        //5.修改数据库中的专辑的购买量
        rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_STAT_UPDATE,orderNo);
        log.info("发送rabbitmq消息 -->  修改mysql中的专辑购买量维度数据");

    }


    /**
     * 分页查询用户订单列表
     * @param page 分页参数
     * @param userId 用户id
     * @return 分页数据
     */
    @Override
    public IPage<OrderInfo> findUserPage(IPage<OrderInfo> page, Long userId) {
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getUserId,userId);
        wrapper.eq(OrderInfo::getIsDeleted,0);
        wrapper.orderByDesc(OrderInfo::getCreateTime);

        IPage<OrderInfo> result = orderInfoMapper.selectPage(page, wrapper);
        List<OrderInfo> records = result.getRecords();
        records.stream().forEach(orderInfo -> {

            List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderInfo.getId()));
            orderInfo.setOrderDetailList(orderDetailList);
            List<OrderDerate> orderDerateList = orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderInfo.getId()));
            orderInfo.setOrderDerateList(orderDerateList);

            String orderStatusName = getOrderStatusName(orderInfo.getOrderStatus());
            orderInfo.setOrderStatusName(orderStatusName);

            String payWayName = getPayWayName(orderInfo.getPayWay());
            orderInfo.setPayWayName(payWayName);

        });

        result.setRecords(records);

        return result;

    }

    /**
     * 组装UserPaidRecordVo对象
     * @param orderInfo 订单信息
     * @return UserPaidRecordVo对象
     */
    private UserPaidRecordVo prepareUserPaidRecordVo(OrderInfo orderInfo) {
        UserPaidRecordVo userPaidRecordVo = new UserPaidRecordVo();
        userPaidRecordVo.setOrderNo(orderInfo.getOrderNo());
        userPaidRecordVo.setUserId(orderInfo.getUserId());
        userPaidRecordVo.setItemType(orderInfo.getItemType());

        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        List<Long> itemIdList = orderDetailList.stream().map(OrderDetail::getItemId).toList();

        userPaidRecordVo.setItemIdList(itemIdList);

        return userPaidRecordVo;
    }
}
